/*******************************************************************************
 * Copyright (c) 2014-6-26 @author <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a>.
 * All rights reserved.
 *
 * Contributors:
 *     <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a> - initial API and implementation
 ******************************************************************************/
package com.foreveross.project.projectonline.jfinal.plugin;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import org.iff.infra.util.FCS;
import org.iff.infra.util.Logger;

/**
 * @author <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a> 
 * @since 2014-6-26
 */
public class CacheKit {

	protected static Cacheable cacheable = new CacheKit().new MapCacheable();

	public static void setKit(Object kit) {
		if (kit instanceof String && "Jedis".equalsIgnoreCase(kit.toString())) {
			cacheable = new CacheKit().new JedisCacheable();
		} else {
			cacheable = new CacheKit().new MapCacheable();
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T get(String key) {
		return (T) cacheable.get(key);
	}

	public static void set(String key, Object value) {
		cacheable.set(key, value);
	}

	public static void set(String key, Object value, int seconds) {
		cacheable.set(key, value, seconds);
	}

	public static void del(String key) {
		cacheable.del(key);
	}

	public interface Cacheable {
		<T> T get(String key);

		void set(String key, Object value);

		void set(String key, Object value, int seconds);

		void del(String key);
	}

	public class MapCacheable implements Cacheable {

		private Map<String, Object> map = new HashMap<String, Object>(1024);

		public void del(String key) {
			map.remove(key);
		}

		@SuppressWarnings("unchecked")
		public <T> T get(String key) {
			return (T) map.get(key);
		}

		public void set(String key, Object value) {
			if (map.size() > 1000) {
				int count = 500;
				for (String k : map.keySet()) {
					if (count-- > 0) {
						map.remove(k);
					}
				}
			}
			map.put(key, value);
		}

		public void set(String key, Object value, int seconds) {
			set(key, value);
		}
	}

	public class JedisCacheable implements Cacheable {

		public JedisCacheable() {
		}

		public void del(String key) {
			JedisSentinelKit.del(key);
		}

		public <T> T get(String key) {
			return (T) JedisSentinelKit.get(key);
		}

		public void set(String key, Object value) {
			if (value instanceof Serializable) {
				JedisSentinelKit.set(key, (Serializable) value);
			} else {
				Logger
						.warn(FCS
								.get(
										"CacheKit.JedisCacheable.set(), value is not instanceof Serializable:{0}",
										value));
			}
		}

		public void set(String key, Object value, int seconds) {
			if (value instanceof Serializable) {
				JedisSentinelKit.set(key, (Serializable) value, seconds);
			} else {
				Logger
						.warn(FCS
								.get(
										"CacheKit.JedisCacheable.set(), value is not instanceof Serializable:{0}",
										value));
			}
		}
	}
}
